<template>
	<div class="jenkins-build-container" v-if="props.operatorNode && props.operatorNode.data.nodeType == 'leaf' && props.operatorItemVersion">
		<!-- 操作表单区域 -->
		<div class="jenkins-header">
			<div class="header-card">
				<div class="custom-form">
					<div class="form-item">
						<label class="form-label">分支:</label>
						<div class="form-control">
							<el-select size="normal" style="width: 200px;" v-model="state.build.branch" placeholder="请选择分支">
								<el-option v-for="br in state.nodeExtraConfig.branches" :key="br" :label="br" :value="br"></el-option>
							</el-select>
						</div>
					</div>
					<div class="form-item"  v-if="props.operatorNode.data.deployType == 'node'">
						<label class="form-label">部署服务器:</label>
						<div class="form-control">
							<el-checkbox-group v-model="state.build.deployIps">
								<el-checkbox v-for="option in state.nodeExtraConfig.deployIps" :label="option" :key="option"></el-checkbox>
							</el-checkbox-group>
						</div>
					</div>
					<div class="form-item">
						<div class="form-control">
							<el-button size="default" type="warning" @click="handleCompile">
								<el-icon>
									<ele-Folder />
								</el-icon>
								执行流水线
							</el-button>
						</div>
					</div>
				</div>
			</div>
		</div>
		
		<!-- 内容区域 -->
		<div class="jenkins-content">
			<div class="content-card">
				<el-tabs v-model="state.activeName" type="border-card" @tab-click="handleTabClick" class="jenkins-tabs">
					<el-tab-pane name="buildRecord">
						<template #label> 编译记录 <i class="el-icon-refresh"></i></template>
						<div class="tab-content-wrapper">
							<div class="table-container">
								<el-table :data="state.buildData.data" v-loading="state.tableData.loading" style="width: 100%;">
									<el-table-column prop="time" label="日期" width="180"></el-table-column>
									<el-table-column prop="jobName" label="JobName"></el-table-column>
									<el-table-column prop="buildNumber" label="编译号"></el-table-column>
									<el-table-column prop="branch" label="分支"></el-table-column>
									<el-table-column prop="deployType" label="部署类型"></el-table-column>
									<el-table-column prop="deployIps" label="部署位置">
										<template #default="scope">
											<span>{{ displayDeployPosition(scope.row) }}</span>
										</template>
									</el-table-column>
									<el-table-column prop="status" label="状态">
										<template #default="scope">
											<el-tag :type="filterStatus(scope.row.status)" disable-transitions>{{ scope.row.status }}</el-tag>
										</template>
									</el-table-column>
									<el-table-column label="操作" align="center">
										<template #default="{ row }">
											<el-button
												v-if="row.status == 'SUCCESS' && state.buildData.param.pageNum == 1"
												type="warning"
												text
												size="small"
												@click.native.stop="handleRollback(row)"
											>
												回滚
											</el-button>
											<el-button v-if="row.status != 'PENDING'" type="primary" text size="small" @click.native.stop="handleGetLog(row)">
												获取日志
											</el-button>
										</template>
									</el-table-column>
								</el-table>
							</div>
							<div class="pagination-container">
								<el-pagination
									class="mt15"
									:pager-count="5"
									:page-sizes="[5]"
									@current-change="onHandleCurrentChange"
									v-model:current-page="state.buildData.param.pageNum"
									background
									v-model:page-size="state.buildData.param.pageSize"
									layout="total, sizes, prev, pager, next, jumper"
									:total="state.buildData.total"
								>
								</el-pagination>
							</div>
						</div>
					</el-tab-pane>
					<el-tab-pane name="rollbackRecord">
						<template #label> 回滚记录 <i class="el-icon-refresh"></i></template>
						<div class="tab-content-wrapper">
							<div class="table-container">
								<el-table :data="state.rollbackData.data" v-loading="state.tableData.loading" style="width: 100%">
									<el-table-column prop="time" label="日期" width="180"></el-table-column>
									<el-table-column prop="jobName" label="JobName" width="180"></el-table-column>
									<el-table-column prop="buildNumber" label="编译号"></el-table-column>
									<el-table-column prop="branch" label="分支"></el-table-column>
									<el-table-column prop="deployType" label="部署类型"></el-table-column>
									<el-table-column prop="deployIps" label="部署位置">
										<template #default="scope">
											<span>{{ displayDeployPosition(scope.row) }}</span>
										</template>
									</el-table-column>
									<el-table-column prop="rollbackBuildNumber" label="回滚版本"></el-table-column>
									<el-table-column prop="status" label="状态">
										<template #default="scope">
											<el-tag :type="filterStatus(scope.row.status)" disable-transitions>{{ scope.row.status }}</el-tag>
										</template>
									</el-table-column>
									<el-table-column label="操作" align="center">
										<template #default="{ row }">
											<el-button v-if="row.status != 'PENDING'" type="primary" size="small" @click.native.stop="handleGetLog(row)"> 获取日志 </el-button>
										</template>
									</el-table-column>
								</el-table>
							</div>
							<div class="pagination-container">
								<el-pagination
									class="mt15"
									:pager-count="5"
									:page-sizes="[5]"
									@current-change="onHandleCurrentChange"
									v-model:current-page="state.rollbackData.param.pageNum"
									background
									v-model:page-size="state.rollbackData.param.pageSize"
									layout="total, sizes, prev, pager, next, jumper"
									:total="state.rollbackData.total"
								>
								</el-pagination>
							</div>
						</div>
					</el-tab-pane>
				</el-tabs>
			</div>
		</div>
		
		<LogDialog ref="logDialogRef" :row="state.logRow"></LogDialog>
	</div>
</template>

<script setup lang="ts" name="jenkinsBuild">
import { reactive, onMounted, ref, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
import { itemVersionApi } from '/@/api/itemVersion';
import LogDialog from '/@/views/item/logDialog.vue';

const logDialogRef = ref();

const props = defineProps({
	operatorNode: {
		type: Object,
		default: () => {
			return {};
		},
	},
	operatorItemVersion: {
		type: Object,
		default: () => {
			return {};
		},
	},
});

// 定义变量内容
const state = reactive({
	// operatorNode: undefined,
	// operatorItemVersion: undefined,
	traceStatusWs: undefined,
	logRow: undefined,
	activeName: 'buildRecord',
	nodeExtraConfig: {
		branches: [],
		deployIps: [],
	},
	build: {
		id: '',
		name: '',
		branch: 'master',
		deployIps: [],
	},
	buildData: {
		data: [],
		total: 0,
		param: {
			pageNum: 1,
			pageSize: 5,
		},
	},
	rollbackData: {
		data: [],
		total: 0,
		param: {
			pageNum: 1,
			pageSize: 10,
		},
	},
	tableData: {
		loading: false,
	},
});

const setUpData = async () => {
	state.nodeExtraConfig.deployIps = props.operatorNode.data.deployIps.split(',');
	itemVersionApi()
		.getBuildBranch(props.operatorItemVersion)
		.then((res) => {
			state.nodeExtraConfig.branches = res.data;
		})
		.catch((err) => {
			ElMessage.error(err.msg);
		});
	getTableData();
};

const handleCompile = () => {
	var params = {
		item_version_id: props.operatorItemVersion.id,
		name: props.operatorNode.data.name,
		deploy_ips: state.build.deployIps.join(','),
		branch: state.build.branch,
	};
	itemVersionApi()
		.jobBuild(params)
		.then((res) => {
			ElMessage.success(res.msg);
			getBuildData();
		})
		.catch((err) => {
			ElMessage.error(err.msg);
		});
};

// 初始化表格数据
const getTableData = () => {
	state.tableData.loading = true;
	getTabData(state.activeName);
	setTimeout(() => {
		state.tableData.loading = false;
	}, 500);
};

const wsRecordsStatus = (traceRecords: any, traceType: string) => {
	// 创建WebSocket连接
	let socket = null;
	if (traceType == 'build') {
		socket = new WebSocket('ws://localhost:8080/jenkins/wsBuildsStatus');
	} else if (traceType == 'rollback') {
		socket = new WebSocket('ws://localhost:8080/jenkins/wsRollbacksStatus');
	}

	if (state.traceStatusWs) {
		state.traceStatusWs.send('close');
		const oldSocket = state.traceStatusWs;
		nextTick(() => {
			oldSocket.close();
		});
	}

	if (!socket) {
		return;
	}

	state.traceStatusWs = socket;
	// 监听连接成功事件
	socket.addEventListener('open', () => {
		console.log('Status WebSocket连接已建立');
		const ids = traceRecords.map((rb) => rb.id);
		// 发送消息给服务器
		socket.send(JSON.stringify({ ids: ids }));
	});

	// 监听接收消息事件
	socket.addEventListener('message', (event) => {
		const message = event.data;
		if (message == 'pong') {
			console.log('接收到后端: ' + message);
			return;
		}
		var serverRecord = JSON.parse(message);
		if (traceType == 'build') {
			// 遍历buildData，查找与serverRecord.id相同的记录
			findRecordAndReplace(state.buildData.data, serverRecord);
		} else if (traceType == 'rollback') {
			// 遍历rollbackData，查找与serverRecord.id相同的记录
			findRecordAndReplace(state.rollbackData.data, serverRecord);
		}
	});

	// 监听连接关闭事件
	socket.addEventListener('close', () => {
		console.log('Status WebSocket连接已关闭');
		state.traceStatusWs = undefined;
	});

	// 监听连接错误事件
	socket.addEventListener('error', (error) => {
		ElMessage.error('Status WebSocket连接错误:' + error);
	});
};

// 查找记录并替换
const findRecordAndReplace = (data: Array, serverRecord: any) => {
	let index = data.findIndex((item) => item.id == serverRecord.id);
	if (index !== -1) {
		data.splice(index, 1, serverRecord);
	}
};

const getRollbackData = () => {
	let query = {
		job_name: 'cus-pipeline/' + props.operatorItemVersion.id,
		page: state.buildData.param.pageNum,
		size: state.buildData.param.pageSize,
	};
	itemVersionApi()
		.getRollbacks(query)
		.then((res) => {
			state.tableData.loading = false;
			state.rollbackData.data = res.data.records;
			state.rollbackData.total = res.data.total;
			// 遍历jobBuilds 持续更改其中状态不为SUCCESS,FAILURE的
			let traceJobBuilds = [];
			for (const jb of state.rollbackData.data) {
				if (jb.status == 'SUCCESS' || jb.status == 'FAILURE') {
					continue;
				}
				traceJobBuilds.push(jb);
			}
			if (traceJobBuilds.length > 0) {
				nextTick(() => {
					wsRecordsStatus(traceJobBuilds, 'rollback');
				});
			}
		});
};

const getBuildData = () => {
	let query = {
		job_name: 'cus-pipeline/' + props.operatorItemVersion.id,
		page: state.buildData.param.pageNum,
		size: state.buildData.param.pageSize,
	};
	itemVersionApi()
		.getBuilds(query)
		.then((res) => {
			state.tableData.loading = false;
			state.buildData.data = res.data.records;
			state.buildData.total = res.data.total;
			// 遍历jobBuilds 持续更改其中状态不为SUCCESS,FAILURE的
			let traceJobBuilds = [];
			for (const jb of state.buildData.data) {
				if (jb.status == 'SUCCESS' || jb.status == 'FAILURE') {
					continue;
				}
				traceJobBuilds.push(jb);
			}
			if (traceJobBuilds.length > 0) {
				nextTick(() => {
					wsRecordsStatus(traceJobBuilds, 'build');
				});
				// wsRecordsStatus(traceJobBuilds, 'build');
			}
		});
};

const handleTabClick = (tab) => {
	state.tableData.loading = true;
	getTabData(tab.paneName);
};

const getTabData = (paneName) => {
	if (paneName == 'rollbackRecord') {
		getRollbackData();
	} else if (paneName == 'buildRecord') {
		getBuildData();
	}
};

const displayDeployPosition = (row) => {
	if (row.deployType == 'k8s') {
		return row.deployClusterName;
	} else if (row.deployType == 'node') {
		return row.deployIps;
	}
	return '-';
};

const filterStatus = (status) => {
	if (status == 'PENDING') {
		return 'info';
	} else if (status == 'SUCCESS') {
		return 'success';
	} else if (status == 'FAILURE') {
		return 'danger';
	}
};

const handleRollback = (row) => {
	//回滚数据
	var params = {
		item_version_id: props.operatorItemVersion.id,
		jenkins_job_build_id: row.id,
	};
	itemVersionApi()
		.jobRollback(params)
		.then((res) => {
			ElMessage.success(res.msg);
		})
		.catch((err) => {
			ElMessage.error(err.msg);
		});
};

const onHandleCurrentChange = () => {
	getTabData(state.activeName);
};

const handleGetLog = (row) => {
	state.logRow = row;
	logDialogRef.value.openDialog();
};

// 页面加载时
onMounted(() => {
	// getTableData();
});

defineExpose({
	setUpData,
});
</script>
<style scoped lang="scss">
/* 主容器样式 */
.jenkins-build-container {
	height: 100%;
	display: flex;
	flex-direction: column;
	background: linear-gradient(135deg, #f0f4ff 0%, #e6eeff 100%);
	padding: 12px;
	gap: 8px;
	overflow: hidden;
}

/* 头部区域样式 */
.jenkins-header {
	flex-shrink: 0;
}

.header-card {
	border-radius: 8px;
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
	border: 1px solid rgba(255, 255, 255, 0.6);
	background: rgba(255, 255, 255, 0.9);
	backdrop-filter: blur(10px);
	padding: 8px 8px;
}


/* 自定义表单样式 */
.custom-form {
	display: flex;
	align-items: center;
	flex-wrap: nowrap;
	gap: 16px;
	width: 100%;
	margin: 0;
}

.form-item {
	display: flex;
	align-items: center;
	flex-shrink: 0;
	gap: 8px;
}

.form-label {
	font-size: 13px;
	color: #606266;
	line-height: 28px;
	height: 28px;
	display: flex;
	align-items: center;
	white-space: nowrap;
	font-weight: 500;
}

.form-control {
	display: flex;
	align-items: center;
	height: 28px;
	min-height: 28px;
}

/* Element Plus 组件样式优化 */
.custom-form :deep(.el-select) {
	height: 28px;
}

.custom-form :deep(.el-select .el-input__inner) {
	height: 28px;
	line-height: 28px;
}

.custom-form :deep(.el-checkbox-group) {
	display: flex;
	align-items: center;
	height: 28px;
	gap: 8px;
}

.custom-form :deep(.el-checkbox) {
	height: 28px;
	display: flex;
	align-items: center;
	margin-right: 8px;
}

.custom-form :deep(.el-button) {
	padding: 6px 12px;
	height: 28px;
	font-size: 13px;
	display: flex;
	align-items: center;
	justify-content: center;
	white-space: nowrap;
}

/* 响应式处理 */
@media (max-width: 1200px) {
	.custom-form {
		flex-wrap: wrap;
		gap: 12px;
	}
}

/* 内容区域样式 */
.jenkins-content {
	flex: 1;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	min-height: 0;
}

.content-card {
	flex: 1;
	display: flex;
	flex-direction: column;
	border-radius: 12px;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
	border: 1px solid rgba(255, 255, 255, 0.6);
	background: rgba(255, 255, 255, 0.9);
	backdrop-filter: blur(10px);
	overflow: hidden;
	padding: 0;
}

/* 标签页样式 */
.jenkins-tabs {
	flex: 1;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	margin: 8px;
	border-radius: 8px;
}

.jenkins-tabs :deep(.el-tabs__content) {
	flex: 1;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	padding: 0;
	margin: 0;
}

.jenkins-tabs :deep(.el-tab-pane) {
	flex: 1;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	height: 100%;
	padding: 0;
}

/* 标签页内容包装器 */
.tab-content-wrapper {
	flex: 1;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	padding: 8px;
	gap: 8px;
}

/* 表格容器样式 */
.table-container {
	flex: 1;
	overflow-y: auto;
	min-height: 200px;
	border-radius: 8px;
	border: 1px solid rgba(0, 0, 0, 0.06);
	background: rgba(255, 255, 255, 0.8);
}

/* 分页容器样式 */
.pagination-container {
	flex-shrink: 0;
	padding-top: 8px;
	border-top: 1px solid rgba(0, 0, 0, 0.06);
	background: rgba(255, 255, 255, 0.9);
	border-radius: 0 0 8px 8px;
}

/* 自定义滚动条样式 */
.table-container::-webkit-scrollbar {
	width: 8px;
}

.table-container::-webkit-scrollbar-track {
	background: rgba(0, 0, 0, 0.05);
	border-radius: 10px;
}

.table-container::-webkit-scrollbar-thumb {
	background-color: #764ba2;
	border-radius: 10px;
	border: 2px solid transparent;
	background-clip: content-box;
	transition: background-color 0.3s ease;
}

.table-container::-webkit-scrollbar-thumb:hover {
	background-color: #667eea;
}

/* 表格样式优化 */
.table-container :deep(.el-table) {
	border-radius: 8px;
	overflow: hidden;
}

.table-container :deep(.el-table__header) {
	background: linear-gradient(135deg, #f8f9ff 0%, #f0f4ff 100%);
}

.table-container :deep(.el-table__body tr:hover) {
	background-color: rgba(102, 126, 234, 0.05);
}

/* 分页样式优化 */
.pagination-container :deep(.el-pagination) {
	justify-content: center;
}

.pagination-container :deep(.el-pagination .btn-next),
.pagination-container :deep(.el-pagination .btn-prev) {
	border-radius: 6px;
}

.pagination-container :deep(.el-pagination .el-pager li) {
	border-radius: 6px;
	margin: 0 2px;
}

/* 响应式设计 */
@media (max-width: 768px) {
	.jenkins-build-container {
		padding: 12px;
		gap: 12px;
	}
	
	.tab-content-wrapper {
		padding: 12px;
		gap: 12px;
	}
}
</style>